#ifndef __ANIMA__H__
#define __ANIMA__H__
#define PIvalue 3.14159265358979323846

// This file is only used to define animate functions;
extern double pow(double X, double Y);
extern double round(double X);
extern double floor(double X);
extern double ceil(double X);
extern double sin(double x);
// --------------Animation---------------
// Expo: Out only
short inline easeOutExpo(short begin, short end, double const& time)
{
    return short(((end - begin) * (time >= 1 ? 1 : 1.000000 - pow(2, -10 * time)) + begin));
}
inline short& easeOutExpo(short& input, short begin, short end, const double& time)
{
    return input = easeOutExpo(begin, end, time);
}

// Expo: In and Out
short inline easeInOutExpo(short begin, short end, double const& time)
{
    return short(round((end - begin) * (time == 0 ? 0
                                        //: time == 1  ? 1
                                        : time < 0.5 ? pow(2, 20 * time - 10) / 2
                                                     : (2 - pow(2, -20 * time + 10)) / 2)) +
                 begin);
}
inline short& easeInOutExpo(short& input, short begin, short end, const double& time)
{
    return input = easeInOutExpo(begin, end, time);
}

// Quint: Out only
short inline easeOutQuint(short begin, short end, double const& time)
{
    return short(((end - begin) * (1.000000 - pow(1 - time, 5))) + begin);
}
inline short& easeOutQuint(short& input, short begin, short end, double const& time)
{
    return input = easeOutQuint(begin, end, time);
}
// Quint: Out only
short inline easeInOutQuint(short begin, short end, double const& time)
{
    return short(
        round((end - begin) * (time < 0.5 ? 16 * time * time * time * time * time : 1 - pow(-2 * time + 2, 5) / 2)) +
        begin);
}
inline short& easeInOutQuint(short& input, short begin, short end, double const& time)
{
    return input = easeInOutQuint(begin, end, time);
}
short inline WaveSin(short begin, short end, double PeriodScale)
{
    PeriodScale = PeriodScale - floor(PeriodScale); // x - [x] 取x的小数部分
    if (PeriodScale < 0) PeriodScale += 1;          // 如果x是负数，加上1使其变为正数
    return short((end - begin) * sin(2 * PIvalue * PeriodScale - PIvalue) + begin);
}
inline short& WaveSin(short& input, short begin, short end, double PeriodScale)
{
    return input = WaveSin(begin, end, PeriodScale);
}
short inline Mapping(double input, short begin, short end)
{
    return short(round((end - begin) * input + begin));
}
short inline Mapping(short input, short begin, short end, short startwith = 0, short endwith = 1000)
{
    double t = 1.0000000 * (endwith - startwith);
    t = input / t;
    return short(round((end - begin) * t + begin));
}

//----------------------------------------
#else
#define WARNING__REDEFINE
#endif